package com.sinochem.yunlian.ship.common.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;

/**
 * Created by wangshichun on 2016/4/18.
 */
public class PoolingHttpUtil {
    private static final Logger logger = LoggerFactory.getLogger(PoolingHttpUtil.class);

    private static CloseableHttpClient httpClient;
    private static PoolingHttpUtilParameter parameter = new PoolingHttpUtilParameter();


    static void setConfig(Integer httpPoolMaxConnection, Integer httpPoolMaxConnectionPerRoute, Integer connectionRequestTimeout,
                          Integer connectTimeout, Integer socketTimeout) {
        parameter.httpPoolMaxConnection = httpPoolMaxConnection;
        parameter.httpPoolMaxConnectionPerRoute = httpPoolMaxConnectionPerRoute;
        parameter.connectionRequestTimeout = connectionRequestTimeout;
        parameter.connectTimeout = connectTimeout;
        parameter.socketTimeout = socketTimeout;
    }

    private static void checkInit() {
        if (null != httpClient)
            return;

        synchronized (PoolingHttpUtil.class) {
            // 设置连接池
            final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
            cm.setMaxTotal(parameter.httpPoolMaxConnection); // 连接池最大连接数
            cm.setDefaultMaxPerRoute(parameter.httpPoolMaxConnectionPerRoute); // 每个对端服务器在本机最多有多少个连接
            cm.setDefaultSocketConfig(SocketConfig.custom()
                    .setSoTimeout(parameter.socketTimeout)
                    .setSoKeepAlive(true)
                    .build());

            // 注册关闭钩子
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (null != httpClient)
                            httpClient.close();
                    } catch (Exception e) {
                        logger.error("关闭http连接池时出错：" + e.getMessage(), e);
                    }
                }
            }));

            // 钩子连接客户端
            CloseableHttpClient temp = HttpClients.custom()
                    .setConnectionManager(cm)
                    .setDefaultRequestConfig(RequestConfig.custom()
                            .setConnectionRequestTimeout(parameter.connectionRequestTimeout)
                            .setConnectTimeout(parameter.connectTimeout)
                            .setSocketTimeout(parameter.socketTimeout)
                            .setRedirectsEnabled(false)
                            .build())
                    .build();
            temp.getClass();
            httpClient = temp;
        }
    }

    public static ByteArrayOutputStream httpGet(String url) {
        checkInit();
        try {
            CloseableHttpResponse response = httpClient.execute(new HttpGet(url));
            try {
                int status = response.getStatusLine().getStatusCode();
                if (status == HttpStatus.SC_NO_CONTENT || status == HttpStatus.SC_NOT_FOUND)
                    return null;
                HttpEntity entity = response.getEntity();
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                StreamUtils.copy(entity.getContent(), out);
                return out;
            } finally {
                response.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static ByteArrayOutputStream httpPost(String url, JSONObject json) {
        return httpPost(url, "application/json", json.toJSONString(), null);
    }

    public static ByteArrayOutputStream httpPost(String url,JSONObject json, String token) {
        return httpPost(url, "application/json", json.toJSONString(),token);
    }

    public static ByteArrayOutputStream httpPost(String url, String contentType, String postContent,String token) {
        checkInit();
        CloseableHttpResponse response;
        try {
            HttpPost post = new HttpPost(url);
            StringEntity se = new StringEntity(postContent);
            se.setContentEncoding("UTF-8");
            se.setContentType(contentType);
            post.setEntity(se);

            if (StringUtils.isNotEmpty(token)) {
                post.setHeader("Authorization", token);
            }

            response = httpClient.execute(post);
            try {
                int status = response.getStatusLine().getStatusCode();
                HttpEntity entity = response.getEntity();
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                StreamUtils.copy(entity.getContent(), out);
                if (status != HttpStatus.SC_OK) {
                    String resp = new String(out.toByteArray(), StandardCharsets.UTF_8);
                    JSONObject respJson = JSON.parseObject(resp);
                    if (respJson.containsKey("error") && respJson.containsKey("error_description")) {
                        logger.error("--error--,msg:{}", respJson.getString("error_description"));
                    }
                    return null;
                }
                return out;
            } finally {
                response.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
//        long time = System.currentTimeMillis();
//        System.out.println(httpGet("http://10.3.255.66:20886/services/promise/13477232852"));
//        System.out.println(System.currentTimeMillis() - time + " ms");
//        randomPwd(8);
    }

    private static class PoolingHttpUtilParameter {
        private int httpPoolMaxConnection = 100;
        private int httpPoolMaxConnectionPerRoute = 20;

        private int connectionRequestTimeout = 2000; // 从连接池获取连接最多等待多少毫秒
        private int connectTimeout = 2000;
        private int socketTimeout = 10000;
    }




}